#include "entityrenderer.h"

#include <iostream>

#include "entities/entity.h"

#include "renderer/shader.h"

#include "gamestate.h"
#include "resourcemanager.h"

EntityRenderer::EntityRenderer(int width, int height, float frustumScale, float zNear, float zFar):SubRenderer(width, height, frustumScale, zNear, zFar){
    std::vector<std::string> unfList1 {"camera", "position", "perspectiveMatrix", "scaleMatrix", "angle", "validPosition"};
    std::vector<std::string> unfList2 {"camera", "position", "perspectiveMatrix", "scaleMatrix", "angle", "color"};
    InitialiseShaderProgram("entity", unfList1);
    InitialiseShaderProgram("entity_picking", unfList2);
}

void EntityRenderer::Draw(){
    std::shared_ptr<Shader> shader = GetShader("entity");
    float cameraPos[] = {camx, camy, camz};
    float scale = 0.1;
    float scaleMatrix[] = {scale, 0, 0, 0, 0, scale, 0, 0, 0, 0, scale, 0, 0, 0, 0, 1};
    int valid_position;

    if(shader==nullptr){
        std::cout<<"Shader name invalid\n";
        return;
    }

    glUseProgram(shader->GetProgram());

    for(auto entity : gamestate->GetAllEntities()){
        float position[] = {(float)entity->Getx(), (float)entity->Gety(), 0, 0};
        Model* model = resourceManager->GetModel(entity->GetModelName());
        if(model == nullptr){
            model = resourceManager->GetModel("simplehouse");
        }

        shader->SetUniform("camera", 3, cameraPos);
        shader->SetUniform("position", 4, position);
        shader->SetUniform("scaleMatrix", 16, scaleMatrix);
        shader->SetUniform("angle", 1, &angle);
        shader->SetUniform("perspectiveMatrix", 16, perspectiveMatrix);
        if(entity->GetID() == gamestate->GetHoverImprovementID()){
            if(entity->IsInAValidPosition()){
                valid_position = 1;
            }
            else{
                valid_position = 0;
            }
        }
        else{
            valid_position = -1;
        }
        shader->SetUniform("validPosition", 1, &valid_position);

        model->Draw();
        if(entity->IsSelected()){
            Model* selection_indicator = resourceManager->GetModel("selection_indicator");
            selection_indicator->Draw();
        }
        if(entity->GetTurnsToComplete()){
            if(entity->IsConstructionPaused()){
                resourceManager->GetModel("pause_symbol")->Draw();
            }
            else{
                resourceManager->GetModel("construction_symbol")->Draw();
            }
        }
    }
    glUseProgram(0);
}

void EntityRenderer::Pick(){
    std::vector<Entity*> entities = gamestate->GetAllEntities();
    std::shared_ptr<Shader> shader = GetShader("entity_picking");
    float cameraPos[] = {camx, camy, camz};
    float scale = 0.1;
    float scaleMatrix[] = {scale, 0, 0, 0, 0, scale, 0, 0, 0, 0, scale, 0, 0, 0, 0, 1};

    if(shader==nullptr){
        std::cout<<"Shader name invalid\n";
        return;
    }

    glUseProgram(shader->GetProgram());

    for(auto entity:entities){
        Model* model = resourceManager->GetModel(entity->GetModelName());
        float position[] = {(float)entity->Getx(), (float)entity->Gety(), 0, 0};
        float color[] = {entity->fRed(), entity->fGreen(), entity->fBlue(), 1};

        if(model == nullptr){
            model = resourceManager->GetModel("simplehouse");
        }

        shader->SetUniform("camera", 3, cameraPos);
        shader->SetUniform("position", 4, position);
        shader->SetUniform("scaleMatrix", 16, scaleMatrix);
        shader->SetUniform("angle", 1, &angle);
        shader->SetUniform("color", 4, color);
        shader->SetUniform("perspectiveMatrix", 16, perspectiveMatrix);

        model->Draw();
    }
    glUseProgram(0);
}
